{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Numpy\n",
    "\n",
    "### Numpy basics\n",
    "\n",
    "NumPy(Numerical Python) 是 Python 语言的一个扩展程序库，支持大量的维度数组与矩阵运算，此外也针对数组运算提供大量的数学函数库。NumPy 是一个运行速度非常快的数学库，主要用于数组计算。\n",
    "\n",
    "NumPy 最重要的一个特点是其 N 维数组对象 ndarray，它是一系列同类型数据的集合，以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组，每个元素在内存中都有相同存储大小的区域，其 内部由以下内容组成：\n",
    "\n",
    "- 一个指向数据（内存或内存映射文件中的一块数据）的指针。\n",
    "- 数据类型或 dtype，描述在数组中的固定大小值的格子。\n",
    "- 一个表示数组形状（shape）的元组，表示各维度大小的元组。\n",
    "- 一个跨度元组（stride），其中的整数指的是为了前进到当前维度下一个元素需要\"跨过\"的字节数。\n",
    "\n",
    "Numpy模块的导入："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "print(np.zeros([2,2]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "创建一个 ndarray 只需调用 NumPy 的 array 函数即可：\n",
    "\n",
    "```\n",
    "np.array(object, dtype = None, copy = True, order = None, subok = False, ndmin = 0)\n",
    "```\n",
    "\n",
    "| object | 数组或嵌套的数列                                          |\n",
    "| ------ | --------------------------------------------------------- |\n",
    "| dtype  | 数组元素的数据类型，可选                                  |\n",
    "| copy   | 对象是否需要复制，可选                                    |\n",
    "| order  | 创建数组的样式，C为行方向，F为列方向，A为任意方向（默认） |\n",
    "| subok  | 默认返回一个与基类类型一致的数组                          |\n",
    "| ndimin | 指定生成数组的最小维度                                    |\n",
    "\n",
    "### Numpy 数据类型和数组创建\n",
    "\n",
    "numpy 支持的数据类型比 Python 内置的类型要多很多，基本上可以和 C 语言的数据类型对应上，其中部分类型对应为 Python 内置的类型。常用 NumPy 基本类型有bool, int, float, int16, int32等。\n",
    "\n",
    "ndarray 数组除了可以使用底层 ndarray 构造器来创建外，也可以通过以下几种方式来创建。\n",
    "\n",
    "##### numpy.empty \n",
    "\n",
    "方法用来创建一个指定形状（shape）、数据类型（dtype）且未初始化的数组：\n",
    "\n",
    "```\n",
    "numpy.empty(shape, dtype = float, order = 'C')\n",
    "```\n",
    "\n",
    "##### numpy.zeros \n",
    "\n",
    "创建指定大小的数组，数组元素以 0 来填充：\n",
    "\n",
    "```\n",
    "umpy.zeros(shape, dtype = float, order = 'C')\n",
    "```\n",
    "\n",
    "##### numpy.ones \n",
    "\n",
    "创建指定形状的数组，数组元素以 1 来填充：\n",
    "\n",
    "```\n",
    "numpy.ones(shape, dtype = None, order = 'C')\n",
    "```\n",
    "\n",
    "\n",
    "参数说明：\n",
    "\n",
    "| 参数  | 描述                                                         |\n",
    "| ----- | ------------------------------------------------------------ |\n",
    "| shape | 数组形状                                                     |\n",
    "| dtype | 数据类型，可选                                               |\n",
    "| order | 有\"C\"和\"F\"两个选项,分别代表，行优先和列优先，在计算机内存中的存储元素的顺序。 |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0]\n",
      " [0]\n",
      " [0]]\n",
      "[[1. 1.]\n",
      " [1. 1.]]\n",
      "[[0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "print(np.empty([3,1],dtype=int))\n",
    "print(np.ones([2,2],dtype=float))\n",
    "print(np.zeros([1,3],dtype=float))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numpy数组操作\n",
    "\n",
    "#### NumPy 广播(Broadcast)\n",
    "\n",
    "广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式， 对数组的算术运算通常在相应的元素上进行。如果两个数组 a 和 b 形状相同，即满足 **a.shape == b.shape**，那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同，且各维度的长度相同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  2  3]\n",
      " [11 12 13]\n",
      " [21 22 23]\n",
      " [31 32 33]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np    \n",
    "a = np.array([[ 0, 0, 0],[10,10,10],[20,20,20],[30,30,30]]) \n",
    "b = np.array([1,2,3]) \n",
    "print(a + b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### NumPy 形状变换\n",
    "\n",
    "##### numpy.reshape \n",
    "\n",
    "该函数可以在不改变数据的条件下修改形状，格式如下： numpy.reshape(arr, newshape, order='C')\n",
    "\n",
    "- arr：要修改形状的数组\n",
    "- newshape：整数或者整数数组，新的形状应当兼容原有形状\n",
    "- order：'C' -- 按行，'F' -- 按列，'A' -- 原顺序，'k' -- 元素在内存中的出现顺序。\n",
    "\n",
    "##### numpy.ravel\n",
    "\n",
    "展平的数组元素，顺序通常是\"C风格\"，返回的是数组视图（view，有点类似 C/C++引用reference的意味），修改会影响原始数组。\n",
    "\n",
    "该函数接收两个参数：\n",
    "\n",
    "```\n",
    "numpy.ravel(a, order='C')\n",
    "```\n",
    "\n",
    "参数说明：\n",
    "\n",
    "- order：'C' -- 按行，'F' -- 按列，'A' -- 原顺序，'K' -- 元素在内存中的出现顺序。\n",
    "\n",
    "numpy.transpose 函数用于对换数组的维度，格式如下：\n",
    "\n",
    "```\n",
    "numpy.transpose(arr, axes)\n",
    "```\n",
    "\n",
    "参数说明:\n",
    "\n",
    "- `arr`：要操作的数组\n",
    "- `axes`：整数列表，对应维度，通常所有维度都会对换。\n",
    "\n",
    "##### numpy.squeeze\n",
    "\n",
    "numpy.squeeze 函数从给定数组的形状中删除一维的条目，函数格式如下：\n",
    "\n",
    "```\n",
    "numpy.squeeze(arr, axis)\n",
    "```\n",
    "\n",
    "参数说明：\n",
    "\n",
    "- `arr`：输入数组\n",
    "- `axis`：整数或整数元组，用于选择形状中一维条目的子集\n",
    "\n",
    "##### numpy.concatenate\n",
    "\n",
    "numpy.concatenate 函数用于沿指定轴连接相同形状的两个或多个数组，格式如下：\n",
    "\n",
    "```\n",
    "numpy.concatenate((a1, a2, ...), axis)\n",
    "```\n",
    "\n",
    "参数说明：\n",
    "\n",
    "- `a1, a2, ...`：相同类型的数组\n",
    "- `axis`：沿着它连接数组的轴，默认为 0\n",
    "\n",
    "##### numpy.stack\n",
    "\n",
    "numpy.stack 函数用于沿新轴连接数组序列，格式如下：\n",
    "\n",
    "```\n",
    "numpy.stack(arrays, axis)\n",
    "```\n",
    "\n",
    "参数说明：\n",
    "\n",
    "- `arrays`相同形状的数组序列\n",
    "- `axis`：返回数组中的轴，输入数组沿着它来堆叠\n",
    "\n",
    "##### numpy.hstack\n",
    "\n",
    "numpy.hstack 是 numpy.stack 函数的变体，它通过水平堆叠来生成数组。\n",
    "\n",
    "##### numpy.vstack\n",
    "\n",
    "numpy.vstack 是 numpy.stack 函数的变体，它通过垂直堆叠来生成数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a=np.linspace(0,5,6)\n",
    "b=np.ones([2,3])\n",
    "print(\"shape A:\" + str(a.shape))\n",
    "print(\"shape B:\" + str(b.shape))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "c=np.reshape(a,[2,3])\n",
    "print(\"reshape A to [2,3]:\\n\" + str(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"reshape A to [3,2]:\\n\" + str(np.reshape(a,[3,2])))\n",
    "print(\"shape of Transpose A: \" + str(np.transpose(c).shape))\n",
    "print(np.vstack([c,b]).shape)\n",
    "print(np.hstack([c,b]).shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Index & Slice\n",
    "https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#arrays-indexing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "solution2": "hidden",
    "solution2_first": true
   },
   "source": [
    "#### 练习\n",
    "只创建数组`a=np.array([0,1,2])`,输出矩阵\n",
    "```\n",
    "[[0 1 2]\n",
    " [2 0 1]\n",
    " [1 2 0]]\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "solution2": "hidden"
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = np.array([0,1,2])\n",
    "b = np.array([a,a,a]).ravel()\n",
    "print(np.vstack([b[0:3],b[2:5],b[4:7]]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numpy函数操作\n",
    "\n",
    "NumPy 包含大量的各种数学运算的函数，包括三角函数，算术运算的函数，复数处理函数等。\n",
    "\n",
    "##### 三角函数\n",
    "\n",
    "NumPy 提供了标准的三角函数：sin()、cos()、tan()。\n",
    "\n",
    "##### 算术函数\n",
    "\n",
    "NumPy 算术函数包含简单的加减乘除: **add()**，**subtract()**，**multiply()** 和 **divide()**。需要注意的是数组必须具有相同的形状或符合数组广播规则。\n",
    "\n",
    "##### 统计函数\n",
    "\n",
    "NumPy 提供了很多统计函数，用于从数组中查找最小元素，最大元素，百分位标准差和方差等。 函数说明如下：\n",
    "\n",
    "numpy.amin() 用于计算数组中的元素沿指定轴的最小值。 numpy.amin() 用于计算数组中的元素沿指定轴的最大值。\n",
    "\n",
    "##### NumPy 排序、条件刷选函数\n",
    "\n",
    "numpy.sort()，numpy.sort() 函数返回输入数组的排序副本。函数格式如下：\n",
    "\n",
    "```\n",
    "numpy.sort(a, axis, kind, order)\n",
    "```\n",
    "\n",
    "##### NumPy 线性代数\n",
    "\n",
    "NumPy 提供了线性代数函数库 **linalg**，该库包含了线性代数所需的所有功能，可以看看下面的说明：\n",
    "\n",
    "| 函数        | 描述                             |\n",
    "| ----------- | -------------------------------- |\n",
    "| dot         | 两个数组的点积，即元素对应相乘。 |\n",
    "| vdot        | 两个向量的点积                   |\n",
    "| inner       | 两个数组的内积                   |\n",
    "| matmu       | 两个数组的矩阵积                 |\n",
    "| determinant | 数组的行列式                     |\n",
    "| solve       | 求解线性矩阵方程                 |\n",
    "| inv         | 计算矩阵的乘法逆矩阵             |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a=np.array([0,30,45,60,90])\n",
    "print(np.sin(a*np.pi/180))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "a=np.array([[3,7],[9,1]])\n",
    "print(a)\n",
    "print(np.sort(a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "b=np.array([[1,2],[3,4]])\n",
    "print(np.dot(a,b))\n",
    "print(np.vdot(a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Numpy载入与保存\n",
    "\n",
    "Numpy 可以读写磁盘上的文本数据或二进制数据。NumPy 为 ndarray 对象引入了一个简单的文件格式：npy。\n",
    "\n",
    "npy 文件用于存储重建 ndarray 所需的数据、图形、dtype 和其他信息。常用的 IO 函数有：\n",
    "\n",
    "- load() 和 save() 函数是读写文件数组数据的两个主要函数，默认情况下，数组是以未压缩的原始二进制格式保存在扩展名为 .npy 的文件中。\n",
    "- savze() 函数用于将多个数组写入文件，默认情况下，数组是以未压缩的原始二进制格式保存在扩展名为 .npz 的文件中。\n",
    "- loadtxt() 和 savetxt() 函数处理正常的文本文件(.txt 等)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "#### 参考资料\n",
    "\n",
    "https://docs.scipy.org/doc/numpy/user/quickstart.html\n",
    "\n",
    "http://www.runoob.com/numpy/numpy-tutorial.html\n",
    "\n",
    "https://blog.csdn.net/csdn15698845876/article/details/73380803\n",
    "\n",
    "https://blog.csdn.net/jiandanjinxin/article/details/78084390?utm_source=blogxgwz0"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
